package  {
	import com.bit101.components.Label;
	import com.bit101.components.PushButton;
	import flash.display.Sprite;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.getTimer;
	import idv.cjcat.signals.Signal;
	import org.osflash.signals.DeluxeSignal;
	
	[SWF(backgroundColor="#FFFFFF", width=300, height=400, frameRate=60)]
	public class Main extends Sprite {
		
		private const COUNT:int = 5000;
		
		private var outputLabel:Label;
		public function Main() {
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			new PushButton(this, 10, 10, "Start Tests", startTests);
			outputLabel = new Label(this, 20, 30);
		}
		
		private var listeners:Array = new Array(COUNT);
		private var dispatcher:IEventDispatcher;
		private var signal:Signal;
		private var as3Signal:DeluxeSignal;
		
		private function startTests(e:Event):void {
			for (var i:int = 0; i < COUNT; ++i) {
				listeners[i] = function(e:Event):void {};
			}
			
			outputLabel.text = "";
			
			dispatcher = new EventDispatcher();
			signal = new Signal(Event);
			as3Signal = new DeluxeSignal(null, Event);
			testAdd();
			println("---------------------------------");
			testDispatch();
			println("---------------------------------");
			testRemove();
			println("---------------------------------");
			
			dispatcher = new EventDispatcher();
			signal = new Signal(Event);
			as3Signal = new DeluxeSignal(null, Event);
			testAddWithPriority();
			println("---------------------------------");
			dispatcher = new EventDispatcher();
			signal = new Signal(Event);
			as3Signal = new DeluxeSignal(null, Event);
			testDuplicateAdd();
			println("---------------------------------");
			dispatcher = new EventDispatcher();
			signal = new Signal(Event);
			as3Signal = new DeluxeSignal(null, Event);
			testDuplicateAddWithPriority();
		}
		
		//------------------------------------------------------------------------------------------------
		
		private function testAdd():void {
			var t:int;
			var i:int;
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) dispatcher.addEventListener(Event.COMPLETE, listeners[i]);
			println("Event dispatcher ADD: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) signal.add(listeners[i]);
			println("CJSignals ADD: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) as3Signal.add(listeners[i]);
			println("AS3 Signals ADD: " + (getTimer() - t) + "ms");
			
		}
		
		private function testDispatch():void {
			var t:int;
			var i:int;
			
			t = getTimer();
			dispatcher.dispatchEvent(new Event(Event.COMPLETE));
			println("Event dispatcher DISPATCH: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			signal.dispatch(new Event(Event.COMPLETE));
			println("CJSignals DISPATCH (sorting required): " + (getTimer() - t) + "ms");
			
			t = getTimer();
			signal.dispatch(new Event(Event.COMPLETE));
			println("CJSignals DISPATCH (sorting not required): " + (getTimer() - t) + "ms");
			
			t = getTimer();
			as3Signal.dispatch(new Event(Event.COMPLETE));
			println("AS3 Signals DISPATCH: " + (getTimer() - t) + "ms");
		}
		
		private function testRemove():void {
			var t:int;
			var i:int;
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) dispatcher.removeEventListener(Event.COMPLETE, listeners[i]);
			println("Event dispatcher REMOVE: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) signal.remove(listeners[i]);
			println("CJSignals REMOVE: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) as3Signal.remove(listeners[i]);
			println("AS3 Signals REMOVE: " + (getTimer() - t) + "ms");
		}
		
		private function testAddWithPriority():void {
			var t:int;
			var i:int;
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) dispatcher.addEventListener(Event.COMPLETE, listeners[i], false, i);
			println("Event dispatcher ADD with priority: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) signal.add(listeners[i], i);
			println("CJSignals ADD with priority: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) as3Signal.add(listeners[i], i);
			println("AS3 Signals ADD with priority: " + (getTimer() - t) + "ms");
		}
		
		private function testDuplicateAdd():void {
			var t:int;
			var i:int;
			var f:Function = function(e:Event):void {};
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) dispatcher.addEventListener(Event.COMPLETE, f);
			println("Event dispatcher DUPLICATE ADD: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) signal.add(f);
			println("CJSignals DUPLICATE ADD: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) as3Signal.add(f);
			println("AS3 Signals DUPLICATE ADD: " + (getTimer() - t) + "ms");
		}
		
		private function testDuplicateAddWithPriority():void {
			var t:int;
			var i:int;
			var f:Function = function(e:Event):void {};
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) dispatcher.addEventListener(Event.COMPLETE, f, false, i);
			println("Event dispatcher DUPLICATE ADD with priority: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) signal.add(f, i);
			println("CJSignals DUPLICATE ADD with priority: " + (getTimer() - t) + "ms");
			
			t = getTimer();
			for (i = 0; i < COUNT; ++i) as3Signal.add(f, i);
			println("AS3 Signals DUPLICATE ADD with priority: " + (getTimer() - t) + "ms");
		}
		
		//------------------------------------------------------------------------------------------------
		
		private function println(text:String = ""):void {
			outputLabel.text += text + "\n";
		}
	}
}